package com.source.sys.controller;

import com.source.sys.entity.Popedom;
import com.source.sys.entity.Role;
import com.source.sys.entity.User;
import com.source.sys.service.RolePopedomService;
import com.source.sys.service.UserRoleService;
import com.source.sys.service.UserService;
import com.source.sys.vo.UserShowVo;
import com.source.syslog.annotation.LogAnnotation;
import com.source.utils.*;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @Author ZZF
 * @Time 2021/03/13 13:45
 */
@Api(tags = "登录注册功能")
@RestController
public class LoginAndRegisterController {
    @Resource
    private UserService userService;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RolePopedomService rolePopedomService;
    @Resource
    private JwtUtils jwtUtils;

    @LogAnnotation(operEvent = "操作类型：登录", operType = 0)
    @ApiOperation(value = "登录")
    @PostMapping("/login")
    public CommonResult login(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    @RequestParam(value = "loginName",required = true)@ApiParam("账号") String loginName,
                                    @RequestParam(value = "password",required = true)@ApiParam("密码") String password,
                                    @RequestParam(value = "remember",required = false,defaultValue = "false")@ApiParam("记住我") Boolean remember){
        UserShowVo loginUser = userService.login(loginName, password);
        //查询数据库，正确则返回token，不正确则返回登录失败
        if(loginUser != null){
            HttpSession session = httpServletRequest.getSession();
            session.setAttribute("loginName",loginName);
            if(remember == true){
                //session60分钟有效时间
                session.setAttribute("password",password);
                session.setMaxInactiveInterval(60*60);
            }
            //将主体放入jwt
            String userId = loginUser.getUserId();
            Role role = userRoleService.getRoleByUserId(userId);
            String roleId = role.getRid();
            String roleName = role.getRName();
            Set<String> popedomNames = new HashSet<>();
            Set<Popedom> popedoms = rolePopedomService.listLevel2PopedomByRid(roleId);
            for (Popedom popedom : popedoms) {
                popedomNames.add(popedom.getPName());
            }
//            System.out.println(popedomNames);
            HashMap<String, Object> subjectMap = new HashMap<>();
            subjectMap.put("userId",userId);
            subjectMap.put("loginName",loginName);
            subjectMap.put("roleId",roleId);
            subjectMap.put("roleName",roleName);
            subjectMap.put("popedoms",popedomNames);
            String jwt = null;
            try {
                //生成jwt
                jwt = jwtUtils.createJWT(userId, subjectMap, (long) SysEnum.JWT_TTLMILLIS.getData());
                System.out.println(jwt);
                //将token放到响应头
                ResponseUtils.placeToken(httpServletResponse,jwt);
            } catch (Exception e) {
                return new CommonResult<>(ResultEnum.ERROR.getCode(),"Token生成失败");
            }
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("user",loginUser);
            resultMap.put("jwt",jwt);
            resultMap.put("sub",subjectMap);
            return new CommonResult<>(ResultEnum.SUCCESS.getCode(),"登录成功",resultMap);
        }else{
            return new CommonResult<>(ResultEnum.ERROR.getCode(),"密码错误，登录失败");
        }
    }

    @ApiOperation(value = "注销")
    @PostMapping("/logout")
    public CommonResult<Object> logout(HttpServletRequest request){
        HttpSession session = request.getSession();
        if(session!=null){
            Object loginNameSession = session.getAttribute("loginName");
            if (loginNameSession!=null){
                session.removeAttribute("loginName");
                return new CommonResult<>(ResultEnum.SUCCESS.getCode(),"注销成功，账号:" + loginNameSession);
            }
        }
        return new CommonResult<>(ResultEnum.ERROR.getCode(),"注销失败");
    }

    @LogAnnotation(operEvent = "操作类型：注册", operType = 5)
    @ApiOperation(value = "注册")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query",name = "loginName",value = "用户名",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "password",value = "密码",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "email",value = "邮箱",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "code",value = "验证码",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "form",name = "file",value = "上传二维码",required = false,dataType = "_file")
    })
    @PostMapping(value = "/register")
    public CommonResult register(String loginName,
                                 String password,
                                 String email,
                                 String code,
                                 @RequestPart(value = "file",required = false) MultipartFile file,
                                 HttpServletRequest request){
        //查询数据库是否有该用户名
        if(userService.findUserExist(loginName)== false) {
            //用户名不存在则注册
            HttpSession session = null;
            Map<String,Object> emailMap = null;
            try{
                session = request.getSession();
                emailMap = (Map) session.getAttribute("emailMap");
            }catch (Exception e){
                return new CommonResult(ResultEnum.ERROR.getCode(),"请发送验证码");
            }
            if(userService.checkReceviceEmail(emailMap,email)){
                //检验验证码是否过期
                if (!userService.checkCodeExpire(emailMap)) {
                    //验证码未过期
                    //验证码是否正确
                    if (userService.checkCodeCorrect(emailMap, code)) {
                        //验证码正确
                        //注册
                        if(userService.register(loginName,password,email,file) == true){
                            //注册成功
                            session.removeAttribute("emailMap");
                            return new CommonResult(ResultEnum.SUCCESS.getCode(),"注册成功，用户名:" + loginName);
                        }else{
                            //注册失败
                            return new CommonResult(ResultEnum.ERROR.getCode(),"注册失败");
                        }
                    } else {
                        return new CommonResult(ResultEnum.ERROR.getCode(), "验证码错误");
                    }
                }else {
                    //验证码过期
                    session.removeAttribute("emailMap");
                    return new CommonResult(ResultEnum.ERROR.getCode(), "验证码过期，请重新发送");
                }
            }else{
                return new CommonResult(ResultEnum.ERROR.getCode(),"验证码错误");
            }

        }else{
            //用户名存在,注册失败
            return new CommonResult(ResultEnum.ERROR.getCode(),"账号存在，注册失败");
        }
    }

    /**
     * 检查用户名是否重复
     * @param loginName
     * @return
     */
    @ApiOperation(value = "检查用户名是否存在")
    @GetMapping("/check/login-name/{loginName}")
    public CommonResult checkUsername(@ApiParam("用户名") @PathVariable("loginName") String loginName){
        if(userService.findUserExist(loginName) == false){
            //不存在该用户名
            return new CommonResult(ResultEnum.SUCCESS.getCode(),"用户名可注册");
        }else{
            return new CommonResult(ResultEnum.ERROR.getCode(),"用户名存在");
        }
    }

    /**
     * 检查邮箱是否重复
     * @param email
     * @return
     */
    @ApiOperation(value = "检查邮箱是否可用")
    @GetMapping("/check/email/{email}")
    public CommonResult checkEmail(@ApiParam("邮箱地址") @PathVariable("email") String email){
        if(userService.checkEmailExist(email) == false){
            //不存在，邮箱可用
            return new CommonResult(ResultEnum.SUCCESS.getCode(),"邮箱可用");
        }else{
            return new CommonResult(ResultEnum.ERROR.getCode(),"邮箱已被注册");
        }
    }

    /**
     * 发送邮箱验证码 ----> 在注册里验证验证码是否过期，是否正确
     */
    @ApiOperation(value = "发送邮箱验证码")
    @GetMapping("/email/{email}")
    public CommonResult sendEmail(@PathVariable("email")@ApiParam("邮箱地址") String email,HttpServletRequest request){
        //[0,1)---->[0,100000-10000)--->[10000,100000)
        int random = (int)(Math.random() * 90000) + 10000;
        String code = random + "";
        System.out.println(code);
        long nowMillis = System.currentTimeMillis();
        int expireTime = 5 * 60 * 1000;
        try {
            userService.sendRegisterEmail(email,code);
        } catch (MessagingException e) {
            return new CommonResult(ResultEnum.ERROR.getCode(),"验证码发送失败，请重新发送");
        } catch (Exception e){
            System.out.println(e.getMessage());
            return new CommonResult(ResultEnum.ERROR.getCode(),"验证码发送失败，请重新发送");
        }
        HttpSession session = request.getSession();
        Map<String, Object> emailMap = new HashMap<>();
        emailMap.put("email",email);
        //验证码
        emailMap.put("code",code);
        //有效时间到expireTime
        emailMap.put("expireTime",new Date(nowMillis + expireTime));
        System.out.println("emailMap: "+ emailMap);
        session.setAttribute("emailMap",emailMap);
        return new CommonResult(ResultEnum.SUCCESS.getCode(),"验证码发送成功，请注意查收");
    }

    /**找回密码
     *
     * @param loginName
     * @param password
     * @param email
     * @param code
     * @param request
     * @return
     */
    @ApiOperation(value = "找回密码(要邮箱验证)")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query",name = "loginName",value = "用户名",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "password",value = "密码",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "email",value = "邮箱地址",required = true,dataType = "String"),
            @ApiImplicitParam(paramType = "query",name = "code",value = "验证码",required = true,dataType = "String"),
    })
    @PostMapping("/get-back-password")
    public CommonResult getBackPassword(String loginName,
                                        String password,
                                        String email,
                                        String code,
                                        HttpServletRequest request){
        if(userService.findUserExist(loginName)){
                //用户名存在
                //检验session中的验证码是否过期
                HttpSession session = null;
                Map<String,Object> emailMap = null;
                try{
                    session = request.getSession();
                     emailMap = (Map) session.getAttribute("emailMap");
                }catch (Exception e){
                    return new CommonResult(ResultEnum.ERROR.getCode(),"请发送验证码");
                }
                if(userService.checkReceviceEmail(emailMap,email)){

                    if(!userService.checkCodeExpire(emailMap)){
                        //未过期
                        //检验是否正确
                        if(userService.checkCodeCorrect(emailMap,code)){
                            //验证码正确
                            //找回密码
                            userService.updateLoginNameAndPwd(loginName, password);
                            session.removeAttribute("emailMap");
                            return new CommonResult(ResultEnum.SUCCESS.getCode(),"修改成功");
                        }else{
                            //验证码错误
                            return new CommonResult(ResultEnum.ERROR.getCode(),"验证码错误");
                        }
                    }else{
                        //过期
                        session.removeAttribute("emailMap");
                        return new CommonResult(ResultEnum.ERROR.getCode(),"验证码已过期，请重新发送验证码");
                    }

                }else{
                    return new CommonResult(ResultEnum.ERROR.getCode(),"验证码错误");
                }



        }
        else{
            return new CommonResult(ResultEnum.ERROR.getCode(),"该用户不存在");
        }
    }

}
